package ua.maxicash.dao;

import org.hibernate.FetchMode;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import ua.maxicash.util.Filter;
import ua.maxicash.util.JqgridQuery;
import ua.maxicash.util.WorkRestrictions;
import ua.maxicash.util.criteria.CriteriaChain;
import ua.maxicash.util.criteria.WorkCriteriaChain;
import ua.maxicash.util.criteria.WorkerCriteriaChain;
import ua.maxicash.vo.SystemUser;
import ua.maxicash.vo.Work;
import ua.maxicash.vo.Worker;

import java.sql.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Repository("appDao")
public class AppDaoImpl implements AppDao {

    @Autowired
    HibernateTemplate hibernateTemplate;

    @Override
    public Set<Work> getActiveWorks() {

        DetachedCriteria crit = DetachedCriteria.forClass(Work.class);
        DetachedCriteria dateCrit = crit.createCriteria("schedule");
        // crit.setFetchMode("schedule", FetchMode.SELECT);
        // crit.createAlias("schedule.workDate","date");
        Date date = new Date(System.currentTimeMillis());
        dateCrit.add(Restrictions.gt("workDate", date));
        List<Work> list = hibernateTemplate.findByCriteria(dateCrit);
        return new HashSet<Work>(list);
    }

    @Override
    public Set<Work> getAllWorks() {

        return new HashSet<Work>(hibernateTemplate.find("from Work"));

    }

    @Override
    public Set<Work> getWorksByJqgridQuery(JqgridQuery jq) {

        CriteriaChain wcc = new WorkCriteriaChain();
        wcc.setUp(jq);

        return new HashSet<Work>(hibernateTemplate.findByCriteria(wcc
                .executeChain()));

    }

    @Override
    public Set<Worker> getWorkersByJqgridQuery(JqgridQuery jq) {

        CriteriaChain wcc = new WorkerCriteriaChain();
        wcc.setUp(jq);
        DetachedCriteria crit = wcc.executeChain();
        return new HashSet<Worker>(hibernateTemplate.findByCriteria(crit));
    }

    @Override
    public Set<Worker> getAllWorkers() {
        return new HashSet<Worker>(
                hibernateTemplate.findByCriteria(DetachedCriteria.forClass(Worker.class)));
    }

    @Override
    @Transactional
    public Set<SystemUser> getLikesOfSystemUser(Long idUser, Integer amount) {

        // TODO rewrite with HQL amount ix fictional!!!
        DetachedCriteria criteria = DetachedCriteria.forClass(SystemUser.class);
        criteria.add(Restrictions.idEq(idUser));
        SystemUser su = (SystemUser) hibernateTemplate.findByCriteria(criteria).get(0);
        Hibernate.initialize(su.getLikes());
        return su.getLikes();

    }

    @Override
    public Set<SystemUser> getAllLikesOfSystemUser(String email) {
        DetachedCriteria criteria = DetachedCriteria.forClass(SystemUser.class);
        criteria.add(Restrictions.eq("email",email));
        SystemUser su = (SystemUser) hibernateTemplate.findByCriteria(criteria).get(0);

        return su.getLikes();

    }

    @Override
    public Set<SystemUser> getAllLikesOfSystemUser(Long idUser) {
        DetachedCriteria criteria = DetachedCriteria.forClass(SystemUser.class);
        criteria.add(Restrictions.idEq(idUser));
        SystemUser su = (SystemUser) hibernateTemplate.findByCriteria(criteria).get(0);

        return su.getLikes();

    }

    @Override
    @Transactional
    public void like(String myEmail, String hisEmail) {

        DetachedCriteria criteria = DetachedCriteria.forClass(SystemUser.class);
        criteria.add(Restrictions.eq("email", myEmail));
        SystemUser me = (SystemUser) hibernateTemplate.findByCriteria(criteria).get(0);
        Set<SystemUser> likes = me.getLikes();

        DetachedCriteria criteria2 = DetachedCriteria.forClass(SystemUser.class);
        criteria2.add(Restrictions.eq("email", hisEmail));
        SystemUser him = (SystemUser) hibernateTemplate.findByCriteria(criteria2).get(0);

        likes.add(him);
        me.setLikes(likes);
        hibernateTemplate.merge(me);

    }

    @Override
    public SystemUser getSystemUserByEmail(String email) {
        DetachedCriteria crit = DetachedCriteria.forClass(SystemUser.class);
        crit.add(Restrictions.eq("email", email));
        List list = hibernateTemplate.findByCriteria(crit);
        if (list.size() == 0) {
            return null;
        } else {
            return (SystemUser) list.get(0);
        }
    }

    public SystemUser getSystemUserById(Long id) {
        DetachedCriteria crit = DetachedCriteria.forClass(SystemUser.class);
        crit.add(Restrictions.idEq(id));
        List list = hibernateTemplate.findByCriteria(crit);
        if (list.size() == 0) {
            return null;
        } else {
            return (SystemUser) list.get(0);
        }
    }

    @Override
    @Transactional
    public void removeFromLikes(Long idUser, Long idLike) {

        Session session = hibernateTemplate.getSessionFactory().getCurrentSession();
        Query query = session.createSQLQuery("delete from SYSTEMUSER_LIKES where ID_USER = :idUser and ID_FRIEND = :idLike");
        query.setLong("idUser",idUser);
        query.setLong("idLike",idLike);
        query.executeUpdate();

    }
}
